home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-06-30 | 23.3 KB | 755 lines |
- /*
- * @(#)BasicSplitPaneDivider.java 1.17 98/02/02
- *
- * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the confidential and proprietary information of Sun
- * Microsystems, Inc. ("Confidential Information"). You shall not
- * disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Sun.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
- * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
- * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
- * THIS SOFTWARE OR ITS DERIVATIVES.
- *
- */
-
- package com.sun.java.swing.plaf.basic;
-
- import java.awt.*;
- import java.awt.event.*;
- import com.sun.java.swing.*;
- import com.sun.java.swing.event.*;
- import com.sun.java.swing.plaf.*;
- import com.sun.java.swing.border.Border;
- import java.beans.*;
- import java.io.*;
-
-
- /**
- * Divider used by BasicSplitPaneUI. Subclassers may wish to override
- * paint to do something more interesting.
- * The border effect is drawn in BasicSplitPaneUI, so if you don't like
- * that border, reset it there.
- * To conditionally drag from certain areas subclass mousePressed and
- * call super when you wish the dragging to begin.
- * <p>
- * Warning: serialized objects of this class will not be compatible with
- * future swing releases. The current serialization support is appropriate
- * for short term storage or RMI between Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- *
- * @version 1.17 02/02/98
- * @author Scott Violet
- */
- public class BasicSplitPaneDivider extends Container
- implements PropertyChangeListener, Serializable
- {
- /** Width or height of the divider based on orientation
- * BasicSplitPaneUI adds two to this. */
-
- protected static final int ONE_TOUCH_SIZE = 5;
- protected static final int ONE_TOUCH_OFFSET = 2;
-
- /** Handles mouse dragging message to do the actual dragging. */
- protected DragController dragger;
- /** UI this instance was created from. */
- protected BasicSplitPaneUI splitPaneUI;
- /** Size of the divider. */
- protected int dividerSize = 0; // default - SET TO 0???
- /** Divider that is used for noncontinuous layout mode. */
- protected Component hiddenDivider;
- /** JSplitPane the receiver is contained in. */
- protected JSplitPane splitPane;
- /** Handle of mouse events. */
- protected MouseHandler mouseHandler;
- /** Orientation of the JSplitPane. */
- protected int orientation;
- /** Button for quickly toggling the left component. */
- protected JButton leftButton;
- /** Button for quickly toggling the right component. */
- protected JButton rightButton;
-
- /** Cursor used for HORIZONTAL_SPLIT splitpanes. */
- static final Cursor horizontalCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
- /** Cursor used for VERTICAL_SPLIT splitpanes. */
- static final Cursor verticalCursor = Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
- /** Default cursor. */
- static final Cursor defaultCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
-
-
- /**
- * Creates an instance of BasicSplitPaneDivider. Registers this
- * instance for mouse events and mouse dragged events.
- */
- public BasicSplitPaneDivider(BasicSplitPaneUI ui) {
- setLayout(new DividerLayout());
- setBasicSplitPaneUI(ui);
- orientation = splitPane.getOrientation();
- setBackground(UIManager.getColor("SplitPane.background"));
- }
-
- /**
- * Sets the SplitPaneUI that is using the receiver.
- */
- public void setBasicSplitPaneUI(BasicSplitPaneUI newUI) {
- if(splitPane != null) {
- splitPane.removePropertyChangeListener(this);
- if(mouseHandler != null) {
- splitPane.removeMouseListener(mouseHandler);
- splitPane.removeMouseMotionListener(mouseHandler);
- mouseHandler = null;
- }
- }
- splitPaneUI = newUI;
- if(newUI != null) {
- splitPane = newUI.getSplitPane();
- if(splitPane != null) {
- if(mouseHandler == null)
- mouseHandler = new MouseHandler();
- splitPane.addMouseListener(mouseHandler);
- splitPane.addMouseMotionListener(mouseHandler);
- splitPane.addPropertyChangeListener(this);
- if(splitPane.isOneTouchExpandable())
- oneTouchExpandableChanged();
- }
- }
- else
- splitPane = null;
- }
-
- /**
- * Returns the <code>SplitPaneUI</code> the receiver is currently
- * in.
- */
- public BasicSplitPaneUI getBasicSplitPaneUI() {
- return splitPaneUI;
- }
-
- /**
- * Sets the size of the divider to <code>newSize</code>. That is
- * the width if the splitpane is <code>HORIZONTAL_SPLIT</code>, or
- * the height of <code>VERTICAL_SPLIT</code>.
- */
- public void setDividerSize(int newSize) {
- dividerSize = newSize;
- }
-
- /**
- * Returns the size of the divider, that is the width if the splitpane
- * is HORIZONTAL_SPLIT, or the height of VERTICAL_SPLIT.
- */
- public int getDividerSize() {
- return dividerSize;
- }
-
- /**
- * Returns dividerSize x dividerSize
- */
- public Dimension getPreferredSize() {
- return new Dimension(getDividerSize(), getDividerSize());
- }
-
- /**
- * Property change event, presumably from the JSplitPane, will message
- * updateOrientation if necessary.
- */
- public void propertyChange(PropertyChangeEvent e) {
- if(e.getSource() == splitPane) {
- if(e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY)) {
- orientation = splitPane.getOrientation();
- invalidate();
- validate();
- }
- else if(e.getPropertyName().equals(JSplitPane.
- ONE_TOUCH_EXPANDABLE_PROPERTY)) {
- oneTouchExpandableChanged();
- }
- }
- }
-
- /**
- * Paints the divider.
- */
- public void paint(Graphics g) {
- super.paint(g);
- }
-
-
- /**
- * Messaged when the oneTouchExpandable value of the JSplitPane the
- * receiver is contained in changes. Will create the
- * <code>leftButton</code> and <code>rightButton</code> if they
- * are null. invalidates the receiver as well.
- */
- protected void oneTouchExpandableChanged() {
- if(splitPane.isOneTouchExpandable() && leftButton == null &&
- rightButton == null) {
- /* Create the left button and add an action listener to
- expand/collapse it. */
- leftButton = createLeftOneTouchButton();
- if(leftButton != null)
- leftButton.addActionListener(new LeftActionListener());
-
-
- /* Create the right button and add an action listener to
- expand/collapse it. */
- rightButton = createRightOneTouchButton();
- if(rightButton != null)
- rightButton.addActionListener(new RightActionListener());
-
- if(leftButton != null && rightButton != null) {
- add(leftButton);
- add(rightButton);
- }
- }
- invalidate();
- validate();
- }
-
- /**
- * Creates and return an instance of JButton that can be used to
- * collapse the left component in the split pane.
- */
- protected JButton createLeftOneTouchButton() {
- JButton b = new JButton() {
- public void setBorder(Border b) {
- }
- public void paint(Graphics g) {
- Dimension size = getSize();
- if(splitPane != null) {
- int[] xs = new int[4];
- int[] ys = new int[4];
- int blockSize = Math.min(getDividerSize(),
- ONE_TOUCH_SIZE);
-
- if(orientation == JSplitPane.VERTICAL_SPLIT)
- {
- xs[0] = xs[3] = 0;
- xs[1] = blockSize;
- xs[2] = blockSize + blockSize;
- ys[0] = ys[2] = ys[3] = blockSize;
- ys[1] = 0;
- }
- else {
- xs[0] = xs[2] = xs[3] = blockSize;
- xs[1] = 0;
- ys[0] = ys[3] = 0;
- ys[1] = blockSize;
- ys[2] = blockSize + blockSize;
- }
- g.setColor(Color.black);
- g.fillPolygon(xs, ys, 4);
- }
- }
- };
- b.setFocusPainted(false);
- b.setBorderPainted(false);
- return b;
- }
-
- /**
- * Creates and return an instance of JButton that can be used to
- * collapse the right component in the split pane.
- */
- protected JButton createRightOneTouchButton() {
- JButton b = new JButton() {
- public void setBorder(Border border) {
- }
- public void paint(Graphics g) {
- if(splitPane != null) {
- int[] xs = new int[4];
- int[] ys = new int[4];
- int blockSize = Math.min(getDividerSize(),
- ONE_TOUCH_SIZE);
-
- if(orientation == JSplitPane.VERTICAL_SPLIT)
- {
- xs[0] = xs[3] = 0;
- xs[1] = blockSize;
- xs[2] = blockSize + blockSize;
- ys[0] = ys[2] = ys[3] = 0;
- ys[1] = blockSize;
- }
- else {
- xs[0] = xs[2] = xs[3] = 0;
- xs[1] = blockSize;
- ys[0] = ys[3] = 0;
- ys[1] = blockSize;
- ys[2] = blockSize + blockSize;
- }
- g.setColor(Color.black);
- g.fillPolygon(xs, ys, 4);
- }
- }
- };
- b.setFocusPainted(false);
- b.setBorderPainted(false);
- return b;
- }
-
- /**
- * Message to prepare for dragging. This messages the BasicSplitPaneUI
- * with startDragging.
- */
- protected void prepareForDragging() {
- splitPaneUI.startDragging();
- }
-
- /**
- * Messages the BasicSplitPaneUI with dragDividerTo that this instance
- * is contained in.
- */
- protected void dragDividerTo(int location) {
- splitPaneUI.dragDividerTo(location);
- }
-
- /**
- * Messages the BasicSplitPaneUI with finishDraggingTo that this instance
- * is contained in.
- */
- protected void finishDraggingTo(int location) {
- splitPaneUI.finishDraggingTo(location);
- }
-
-
- /**
- * MouseHandler is responsible for converting mouse events
- * (released, dragged...) into the appropriate DragController
- * methods.
- * <p>
- * Warning: serialized objects of this class will not be compatible with
- * future swing releases. The current serialization support is appropriate
- * for short term storage or RMI between Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- */
- protected class MouseHandler extends MouseAdapter implements
- MouseMotionListener, Serializable {
-
- /**
- * Starts the dragging session by creating the appropriate instance
- * of DragController.
- */
- public void mousePressed(MouseEvent e) {
- if(e.getSource() == splitPane && dragger == null &&
- splitPane.isEnabled()) {
- Component newHiddenDivider = splitPaneUI.
- getNonContinuousLayoutDivider();
-
- if(hiddenDivider != newHiddenDivider) {
- if(hiddenDivider != null) {
- hiddenDivider.removeMouseListener(this);
- hiddenDivider.removeMouseMotionListener(this);
- }
- hiddenDivider = newHiddenDivider;
- if(hiddenDivider != null) {
- hiddenDivider.addMouseMotionListener(this);
- hiddenDivider.addMouseListener(this);
- }
- }
- if(splitPane.getLeftComponent() != null &&
- splitPane.getRightComponent() != null) {
- if(orientation == JSplitPane.HORIZONTAL_SPLIT)
- dragger = new DragController(e);
- else
- dragger = new VerticalDragController(e);
- if(!dragger.isValid())
- dragger = null;
- else {
- prepareForDragging();
- dragger.continueDrag(e);
- }
- }
- e.consume();
- }
- }
-
- /**
- * If dragg is not null it is messaged with completeDrag.
- */
- public void mouseReleased(MouseEvent e) {
- if(dragger != null) {
- if(e.getSource() == splitPane) {
- dragger.completeDrag(e.getX(), e.getY());
- }
- else if(e.getSource() == hiddenDivider) {
- Point ourLoc = getLocation();
- Point hDividerLoc = hiddenDivider.getLocation();
- int ourX = e.getX() + hDividerLoc.x;
- int ourY = e.getY() + hDividerLoc.y;
-
- dragger.completeDrag(ourX, ourY);
- }
- dragger = null;
- }
- splitPane.setCursor(defaultCursor);
- e.consume();
- }
-
- //
- // MouseMotionListener
- //
- /**
- * If dragger is not null it is messaged with continueDrag.
- */
- public void mouseDragged(MouseEvent e) {
- if(dragger != null) {
- if(e.getSource() == splitPane) {
- dragger.continueDrag(e.getX(), e.getY());
- }
- else if(e.getSource() == hiddenDivider) {
- Point ourLoc = getLocation();
- Point hDividerLoc = hiddenDivider.getLocation();
- int ourX = e.getX() + hDividerLoc.x;
- int ourY = e.getY() + hDividerLoc.y;
-
- dragger.continueDrag(ourX, ourY);
- }
- e.consume();
- }
- }
-
- /**
- * Resets the cursor based on the orientation.
- */
- public void mouseMoved(MouseEvent e) {
- if(dragger != null)
- return;
-
- int eventX = e.getX();
- int eventY = e.getY();
- Rectangle bounds = getBounds();
-
- if(eventX >= bounds.x && (eventX < (bounds.x + bounds.width)) &&
- eventY >= bounds.y && eventY < (bounds.y + bounds.height)) {
- /* Reset the cursor. */
- if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
- if(splitPane.getCursor() != horizontalCursor) {
- splitPane.setCursor(horizontalCursor);
- }
- }
- else if(splitPane.getCursor() != verticalCursor) {
- splitPane.setCursor(verticalCursor);
- }
- }
- else if(splitPane.getCursor() != defaultCursor) {
- splitPane.setCursor(defaultCursor);
- }
- }
- }
-
-
- /**
- * Handles the events during a dragging session for a
- * HORIZONTAL_SPLIT orientated split pane. This continually
- * messages dragDividerTo and then when done messages
- * finishDraggingTo. When an instance is created it should be
- * messaged with isValid() to insure that dragging can happen
- * (dragging won't be allowed if the two views can not be resized).
- * <p>
- * Warning: serialized objects of this class will not be compatible with
- * future swing releases. The current serialization support is appropriate
- * for short term storage or RMI between Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- */
- protected class DragController implements Serializable {
- /** Initial location of the divider. */
- int initialX;
- /** Maximum and minimum positions to drag to. */
- int maxX, minX;
- /** Initial location the mouse down happened at. */
- int offset;
-
- protected DragController(MouseEvent e) {
- Component leftC, rightC;
- JSplitPane splitPane = splitPaneUI.getSplitPane();
- Insets insets = splitPane.getInsets();
- int rightOffset;
-
- if(insets != null)
- rightOffset = insets.right;
- else
- rightOffset = 0;
- initialX = getLocation().x;
- leftC = splitPane.getLeftComponent();
- rightC = splitPane.getRightComponent();
- if(leftC != null && rightC != null) {
- minX = leftC.getMinimumSize().width +
- leftC.getLocation().x;
- maxX = Math.max(0, splitPane.getSize().width -
- (2 + getSize().width + rightOffset) -
- rightC.getMinimumSize().width);
- if(maxX < minX)
- minX = maxX = 0;
- }
- else
- minX = maxX = 0;
- offset = e.getX() - initialX;
- if(offset < -1 || offset > getSize().width)
- maxX = -1;
- }
-
- /**
- * Returns true if the dragging session is valid.
- */
- protected boolean isValid() {
- return (maxX > 0);
- }
-
- /**
- * Returns the new position to put the divider at based on
- * the passed in MouseEvent.
- */
- protected int positionForMouseEvent(MouseEvent e) {
- int newX;
-
- newX = Math.min(maxX, Math.max(minX,
- e.getX() - offset));
- return newX;
- }
-
- /**
- * Returns the x argument, since this is used for horizontal
- * splits.
- */
- protected int getNeededLocation(int x, int y) {
- int newX;
-
- newX = Math.min(maxX, Math.max(minX, x - offset));
- return newX;
- }
-
- protected void continueDrag(int newX, int newY) {
- dragDividerTo(getNeededLocation(newX, newY));
- }
-
- /**
- * Messages dragDividerTo with the new location for the mouse
- * event.
- */
- protected void continueDrag(MouseEvent e) {
- dragDividerTo(positionForMouseEvent(e));
- }
-
- protected void completeDrag(int x, int y) {
- finishDraggingTo(getNeededLocation(x, y));
- }
-
- /**
- * Messages finishDraggingTo with the new location for the mouse
- * event.
- */
- protected void completeDrag(MouseEvent e) {
- finishDraggingTo(positionForMouseEvent(e));
- }
- } // End of BasicSplitPaneDividier.DragController
-
-
- /**
- * Handles the events during a dragging session for a
- * VERTICAL_SPLIT orientated split pane. This continually
- * messages dragDividerTo and then when done messages
- * finishDraggingTo. When an instance is created it should be
- * messaged with isValid() to insure that dragging can happen
- * (dragging won't be allowed if the two views can not be resized).
- */
- protected class VerticalDragController extends DragController {
- /* DragControllers ivars are now in terms of y, not x. */
-
- protected VerticalDragController(MouseEvent e) {
- super(e);
- Component leftC, rightC;
- JSplitPane splitPane = splitPaneUI.getSplitPane();
- Insets insets = splitPane.getInsets();
- int bottomOffset;
-
- if(insets != null)
- bottomOffset = insets.bottom;
- else
- bottomOffset = 0;
- initialX = getLocation().y;
- leftC = splitPane.getLeftComponent();
- rightC = splitPane.getRightComponent();
- if(leftC != null && rightC != null) {
- minX = leftC.getMinimumSize().height +
- leftC.getLocation().y;
- maxX = Math.max(0, splitPane.getSize().height -
- (2 + getSize().height + bottomOffset) -
- rightC.getMinimumSize().height);
- if(maxX < minX)
- minX = maxX = 0;
- }
- else
- minX = maxX = 0;
- offset = e.getY() - initialX;
- if(offset < -1 || offset > getSize().height)
- maxX = -1;
- }
-
- /**
- * Returns the y argument, since this is used for vertical
- * splits.
- */
- protected int getNeededLocation(int x, int y) {
- int newY;
-
- newY = Math.min(maxX, Math.max(minX, y - offset));
- return newY;
- }
-
- /**
- * Returns the new position to put the divider at based on
- * the passed in MouseEvent.
- */
- protected int positionForMouseEvent(MouseEvent e) {
- int newY;
-
- newY = Math.min(maxX, Math.max(minX,
- e.getY() - offset));
- return newY;
- }
-
- } // End of BasicSplitPaneDividier.VerticalDragController
-
-
- /**
- * Used to layout a BasicSplitPaneDivider. Layout for the divider
- * involves appropraitely moving the left/right buttons around.
- * <p>
- * Warning: serialized objects of this class will not be compatible with
- * future swing releases. The current serialization support is appropriate
- * for short term storage or RMI between Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- */
- protected class DividerLayout implements LayoutManager, Serializable {
- public void layoutContainer(Container c) {
- if(leftButton != null && rightButton != null &&
- c == BasicSplitPaneDivider.this) {
- if(splitPane.isOneTouchExpandable()) {
- int blockSize = Math.min(getDividerSize(),
- ONE_TOUCH_SIZE);
-
- if(orientation == JSplitPane.VERTICAL_SPLIT) {
- int y = (c.getSize().height - blockSize) / 2;
-
- leftButton.setBounds(ONE_TOUCH_OFFSET, y,
- blockSize * 2, blockSize);
- rightButton.setBounds(2 * ONE_TOUCH_OFFSET +
- ONE_TOUCH_SIZE * 2, y,
- blockSize * 2, blockSize);
- }
- else {
- int x = (c.getSize().width - blockSize) / 2;
-
- leftButton.setBounds(x, ONE_TOUCH_OFFSET,
- blockSize, blockSize * 2);
- rightButton.setBounds(x, 2 * ONE_TOUCH_OFFSET +
- ONE_TOUCH_SIZE * 2, blockSize,
- blockSize * 2);
- }
- }
- else {
- leftButton.setBounds(-5, -5, 1, 1);
- rightButton.setBounds(-5, -5, 1, 1);
- }
- }
- }
- public Dimension minimumLayoutSize(Container c) {
- return new Dimension(0,0);
- }
- public Dimension preferredLayoutSize(Container c) {
- return new Dimension(0, 0);
- }
- public void removeLayoutComponent(Component c) {}
- public void addLayoutComponent(String string, Component c) {}
- } // End of class BasicSplitPaneDivider.DividerLayout
-
-
- /**
- * Listener for move-left events.
- * <p>
- * Warning: serialized objects of this class will not be compatible with
- * future swing releases. The current serialization support is appropriate
- * for short term storage or RMI between Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- */
- private class LeftActionListener implements ActionListener, Serializable
- {
- public void actionPerformed(ActionEvent e) {
- Insets insets = splitPane.getInsets();
- int currentLoc;
-
- currentLoc = splitPane.getDividerLocation();
- currentLoc += splitPaneUI.getDividerBorderSize();
- if(orientation == JSplitPane.VERTICAL_SPLIT) {
- if(currentLoc >= (splitPane.getHeight() -
- insets.bottom - getDividerSize()))
- splitPane.setDividerLocation(splitPane.
- getLastDividerLocation());
- else
- splitPane.setDividerLocation(0);
- }
- else {
- if(currentLoc >= (splitPane.getWidth() -
- insets.right - getDividerSize()))
- splitPane.setDividerLocation(splitPane.
- getLastDividerLocation());
- else
- splitPane.setDividerLocation(0);
- }
- }
- } // End of class BasicSplitPaneDivider.LeftActionListener
-
-
- /**
- * Listener for move-right events.
- * <p>
- * Warning: serialized objects of this class will not be compatible with
- * future swing releases. The current serialization support is appropriate
- * for short term storage or RMI between Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- */
- private class RightActionListener implements ActionListener, Serializable
- {
- public void actionPerformed(ActionEvent e) {
- Insets insets = splitPane.getInsets();
- int currentLoc;
-
- currentLoc = splitPane.getDividerLocation();
- currentLoc -= splitPaneUI.getDividerBorderSize();
- if(orientation == JSplitPane.VERTICAL_SPLIT) {
- if(currentLoc == insets.top)
- splitPane.setDividerLocation(splitPane
- .getLastDividerLocation());
- else
- splitPane.setDividerLocation(splitPane
- .getHeight() - insets.bottom);
- }
- else {
- if(currentLoc == insets.left)
- splitPane.setDividerLocation(splitPane.
- getLastDividerLocation());
- else
- splitPane.setDividerLocation(splitPane.
- getWidth() - insets.right);
- }
- }
- } // End of class BasicSplitPaneDivider.RightActionListener
- }
-